package cn.com.jenson.service.log.service.impl;

import cn.com.jenson.common.ImportVerifierVo;
import cn.com.jenson.common.SelectVo;
import cn.com.jenson.dao.log.bo.ParkingLogBo;
import cn.com.jenson.dao.log.searchBo.ParkingLogSearchBo;
import cn.com.jenson.dao.log.vo.ParkingLogVo;
import cn.com.jenson.entity.car.Car;
import cn.com.jenson.entity.log.ParkingLog;
import cn.com.jenson.entity.log.QParkingLog;
import cn.com.jenson.entity.user.User;
import cn.com.jenson.exception.BusinessException;
import cn.com.jenson.service.car.repository.CarRepository;
import cn.com.jenson.service.log.repository.ParkingLogRepository;
import cn.com.jenson.service.log.service.ParkingLogService;
import cn.com.jenson.service.user.repository.UserRepository;
import cn.com.jenson.util.TimeUtil;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class ParkingLogServiceImpl implements ParkingLogService {

    @Resource
    private ParkingLogRepository parkingLogRepository;

    @Resource
    private CarRepository carRepository;

    @Resource
    private UserRepository userRepository;

    @Resource
    JPAQueryFactory jpaQueryFactory;

    QParkingLog qParkingLog = QParkingLog.parkingLog;

    @Override
    public Page<ParkingLogVo> pageAll(ParkingLogSearchBo parkingLogSearchBo) {

        JPAQuery<ParkingLog> jpaQuery = jpaQueryFactory
                .selectFrom(qParkingLog)
                .where(getWhere(parkingLogSearchBo));

        List<ParkingLog> list = jpaQuery
                .offset(parkingLogSearchBo.getPageRequest().getOffset())
                .limit(parkingLogSearchBo.getPageRequest().getPageSize())
                .fetch();

        Page<ParkingLogVo> page = new PageImpl<>(
                new ParkingLogVo().fromEntities(list, ParkingLogVo.class),
                parkingLogSearchBo.getPageRequest(),
                jpaQuery.fetchCount()
        );

        supplement(page);

        return page;
    }

    @Override
    public List<ParkingLogVo> listAll(ParkingLogSearchBo parkingLogSearchBo) {
        List<ParkingLogVo> list = new ParkingLogVo().fromEntities(
                jpaQueryFactory.selectFrom(qParkingLog)
                        .where(getWhere(parkingLogSearchBo))
                        .fetch(),
                ParkingLogVo.class
        );

        supplement(list);

        return list;
    }

    @Override
    public ParkingLogVo get(ParkingLogSearchBo parkingLogSearchBo) throws InstantiationException, IllegalAccessException {

        ParkingLogVo parkingLogVo = new ParkingLogVo().fromEntity(
                parkingLogRepository.findByIdAndDeleted(parkingLogSearchBo.getId(), false)
                        .orElseThrow(() -> new BusinessException("找不到id为" + parkingLogSearchBo.getId() + "的停车记录")),
                ParkingLogVo.class
        );

        supplement(parkingLogVo);

        return parkingLogVo;
    }

    @Override
    public BooleanExpression getWhere(ParkingLogSearchBo parkingLogSearchBo) {
        return qParkingLog.deleted.eq(false);
    }

    @Override
    public ParkingLogVo edit(ParkingLogBo parkingLogBo) throws InstantiationException, IllegalAccessException {
        ParkingLog parkingLog = new ParkingLogBo().toEntity(parkingLogBo, ParkingLog.class);
        parkingLog = parkingLogRepository.save(parkingLog);
        return new ParkingLogVo().fromEntity(parkingLog, ParkingLogVo.class);
    }

    @Override
    public List<ParkingLogVo> editAll(List<ParkingLogBo> parkingLogBos) {
        return null;
    }

    @Override
    public ParkingLogVo deleted(ParkingLogSearchBo parkingLogSearchBo) throws InstantiationException, IllegalAccessException {
        return null;
    }

    @Override
    public List<ParkingLogVo> deletedAll(List<ParkingLogSearchBo> parkingLogSearchBos) {
        return null;
    }

    @Override
    public List<ImportVerifierVo> importTemplateVerifiers() {
        return null;
    }

    @Override
    public void importTemplateDownload(HttpServletResponse response) throws IOException {

    }

    @Override
    public List<SelectVo<String, Integer, ParkingLogVo>> option() {
        return null;
    }

    @Override
    public void supplement(ParkingLogVo parkingLogVo) {

    }

    @Override
    public void supplement(List<ParkingLogVo> parkingLogVos) {

    }

    @Override
    public void supplement(Page<ParkingLogVo> parkingLogVos) {
        supplement(parkingLogVos.getContent());
    }

    @Override
    public void in(ParkingLogBo parkingLogBo) {
        List<ParkingLog> parkingLogList = parkingLogRepository.findByCarPlateAndOutDate(parkingLogBo.getCarPlate(), null);
        if (parkingLogList.size() > 1)
            throw new BusinessException("此车未出库");
        boolean isMember = Objects.nonNull(carRepository.findByPlateAndDeleted(parkingLogBo.getCarPlate(), false));
        ParkingLog parkingLog = new ParkingLog(parkingLogBo.getCarPlate(), new Date(), isMember);
        parkingLogRepository.save(parkingLog);
    }

    @Override
    public void out(ParkingLogBo parkingLogBo) {
        List<ParkingLog> parkingLogList = parkingLogRepository.findByCarPlateAndOutDate(parkingLogBo.getCarPlate(), null);
        if (parkingLogList.size() == 0)
            throw new BusinessException("查无此车");
        ParkingLog parkingLog = parkingLogList.stream().findFirst().get();
        parkingLog.setOutDate(new Date());
        parkingLog.setPaymentMethod("现金");
        parkingLog.setMoney(TimeUtil.differenceHour(parkingLog.getInDate(), parkingLog.getOutDate()) * 5);
        User user;
        if (parkingLog.getIsMember()) {
            Car car = carRepository.findByPlateAndDeleted(parkingLogBo.getCarPlate(), false);
            user = userRepository.findByIdAndDeleted(car.getUserId(), false).orElse(new User());
            if (user.getBalance() > 0) {
                parkingLog.setPaymentMethod("余额");
                user.setBalance(user.getBalance() - parkingLog.getMoney());
                userRepository.save(user);
            } else {
                parkingLog.setPaymentMethod("现金");
            }
        }
        parkingLogRepository.save(parkingLog);
    }
}
